﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace SuperX.Common.Scheduler
{
    public class PreciseTimer
    {
        //
        public int Interval
        {
            get
            {
                return this._interval;
            }
            set
            {
                if (value > 50)
                {
                    this._interval = value;
                }
            }
        }

        // 
        public PreciseTimer(int interval, DateTime nextTriggerTime, Action<DateTime> action)
        {
            this.Interval = interval;
            this._nextTriggerTime = nextTriggerTime;
            this._action = action;
            this._timer = new Timer(new TimerCallback(this.Tick), this, 0, this._timeUnit);
        }

        // 
        private void Tick(object state)
        {
            object synObj = this._synObj;
            lock (synObj)
            {
                DateTime now = DateTime.Now;
                if (now >= this._nextTriggerTime)
                {
                    if ((now - this._nextTriggerTime).TotalMilliseconds < (double)this._interval)
                    {
                        this.Invoke(this._nextTriggerTime);
                    }
                    this.UpdataNextTrggierTime(now);
                }
            }
        }

        // 
        private void Invoke(DateTime triggerTime)
        {
            Action<DateTime> action = this._action;
            if (action == null)
            {
                return;
            }
            action(triggerTime);
        }

        // 
        private void UpdataNextTrggierTime(DateTime now)
        {
            if ((now - this._nextTriggerTime).TotalMilliseconds > (double)this._interval)
            {
                double num = Math.Round((now - this._nextTriggerTime).TotalMilliseconds % (double)this._interval, 0);
                this._nextTriggerTime = now.AddMilliseconds((double)this._interval - num);
                return;
            }
            this._nextTriggerTime = this._nextTriggerTime.AddMilliseconds((double)this._interval);
        }

        // 
        public void Stop()
        {
            Timer timer = this._timer;
            if (timer != null)
            {
                timer.Change(-1, -1);
            }
            Timer timer2 = this._timer;
            if (timer2 != null)
            {
                timer2.Dispose();
            }
            this._action = null;
        }

        // 
        private readonly object _synObj = new object();

        // 
        private Timer _timer;

        // 
        private DateTime _nextTriggerTime;

        // 
        private Action<DateTime> _action;

        // 
        private int _timeUnit = 50;

        // 
        private int _interval = 1000;
    }
}
